package com.sh.data.engine.domain.api.service.impl;

import com.google.common.collect.Lists;
import com.sh.data.engine.common.enumDefinition.DataApiApproveStatusEnum;
import com.sh.data.engine.domain.api.model.domain.*;
import com.sh.data.engine.domain.api.service.*;
import org.apache.commons.lang.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author : fuchen
 * @date : 2022/2/10 14:12
 */
@Service
public class DataApiOverviewServiceImpl implements DataApiOverviewService {

    @Autowired
    private DataApiAuthService dataApiAuthService;

    @Autowired
    private DataApiService dataApiService;

    @Autowired
    private DataApiUserStatisticsService dataApiUserStatisticsService;

    @Autowired
    private DataApiCallStatisticsService dataApiCallStatisticsService;

    @Autowired
    private DataApiCallRecordService dataApiCallRecordService;

    /**
     * 全局概览需要auth为 1 type= 0
     *
     * <p>我的概览不要求auth type = 1
     */
    @Override
    public DataApiOverviewSummaryDomain getOverviewSummary(
        Integer type, Long projectId, String userId, Integer isAuth) {
        if (type == 0) {
            Long totalApiByProjectId = dataApiService.getTotalApiByProjectId(projectId);
            Long totalFailApiByProjectId = dataApiService.getTotalFailApiByProjectId(projectId);
            Long totalPublishedApiByProjectId = dataApiService.getTotalPublishedApiByProjectId(projectId);
            Long totalApplyByProjectId = dataApiAuthService.getTotalApplyByProjectId(projectId, null);
            DataApiOverviewSummaryDomain dataApiOverview =
                DataApiOverviewSummaryDomain.builder()
                    .totalCount(totalApiByProjectId)
                    .appliedCount(totalApplyByProjectId)
                    .totalReqCount(totalPublishedApiByProjectId)
                    .totalReqErrCount(totalFailApiByProjectId)
                    .build();

            return dataApiOverview;
        }
        Long totalApplyByProjectIdAndUserId =
            dataApiAuthService.getTotalApplyByProjectIdAndUserId(projectId, null, userId);

        Long totalApiSumByProjectAndUserId =
            dataApiService.getTotalApiSumByProjectAndUserId(projectId, userId);

        Long userTotalCount =
            dataApiUserStatisticsService.getTotalCountByProjectIdAndUserId(projectId, userId);

        Long failCountByProjectIdAndUserId =
            dataApiUserStatisticsService.getFailCountByProjectIdAndUserId(projectId, userId);
        DataApiOverviewSummaryDomain r =
            DataApiOverviewSummaryDomain.builder()
                .publishedCount(totalApiSumByProjectAndUserId)
                .appliedCount(totalApplyByProjectIdAndUserId)
                .totalReqCount(userTotalCount)
                .totalReqErrCount(failCountByProjectIdAndUserId)
                .build();
        return r;
    }

    @Override
    public DataApiApprovalSummaryDomain getApprovalSummary(
        Integer type, Long projectId, String id, Integer isAuth) {

        if (type == 0) {
            Long waitNum =
                dataApiAuthService.getTotalApplyByProjectId(
                    projectId, DataApiApproveStatusEnum.WAIT_APPROVE.getApproveStatus());
            Long passedNum =
                dataApiAuthService.getTotalApplyByProjectId(
                    projectId, DataApiApproveStatusEnum.PASSED.getApproveStatus());
            DataApiApprovalSummaryDomain dataApiApprovalSummaryDomain =
                DataApiApprovalSummaryDomain.builder()
                    .awaitApprovalCount(waitNum)
                    .passedApprovalCount(passedNum)
                    .build();
            return dataApiApprovalSummaryDomain;
        }
        Long waitNum =
            dataApiAuthService.getTotalApplyByProjectIdAndUserId(
                projectId, DataApiApproveStatusEnum.WAIT_APPROVE.getApproveStatus(), id);
        Long passedNum =
            dataApiAuthService.getTotalApplyByProjectIdAndUserId(
                projectId, DataApiApproveStatusEnum.PASSED.getApproveStatus(), id);
        DataApiApprovalSummaryDomain dataApiApprovalSummaryDomain =
            DataApiApprovalSummaryDomain.builder()
                .awaitApprovalCount(waitNum)
                .passedApprovalCount(passedNum)
                .build();
        return dataApiApprovalSummaryDomain;
    }

    @Override
    public List<DataApiReqTrendSummaryDomain> getReqTrendSummary(
        Integer type, String startDate, String endDate, Long projectId, Integer isAuth, String id) {
        List<DataApiReqTrendSummaryDomain> domains = Lists.newArrayList();
        List<DataApiReqTrendSummaryDomain> dataApiReqTrendSummary = Lists.newArrayList();
        if (type == 0) {
            dataApiReqTrendSummary =
                dataApiCallStatisticsService.getDataApiReqTrendSummary(
                    startDate, endDate, projectId, null);
        } else {
            dataApiReqTrendSummary =
                dataApiCallStatisticsService.getDataApiReqTrendSummary(startDate, endDate, projectId, id);
        }

        for (DataApiReqTrendSummaryDomain dataApiReqTrendSummaryDomain : dataApiReqTrendSummary) {
            String date =
                DateFormatUtils.format(dataApiReqTrendSummaryDomain.getStatisticsDate(), "yyyy-MM-dd");
            domains.add(
                DataApiReqTrendSummaryDomain.builder()
                    .time(date)
                    .count(dataApiReqTrendSummaryDomain.getCount())
                    .build());
        }

        Set<String> dates = domains.stream().map(x -> x.getTime()).collect(Collectors.toSet());

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
        LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);

        long daysDiff = ChronoUnit.DAYS.between(start, end);

        for (int i = 0; i <= daysDiff; i++) {
            String d = start.plusDays(i).format(dateTimeFormatter);
            if (!dates.contains(d)) {
                domains.add(DataApiReqTrendSummaryDomain.builder().time(d).count(0L).build());
            }
        }

        domains.sort((o1, o2) -> o1.getTime().compareTo(o2.getTime()));

        return domains;
    }

    @Override
    public List<DataApiTopUserReqSummaryDomain> getTopUserReqSummary(Long projectId) {
        List<DataApiTopUserReqDomain> getDataApiTopUserReqDomainList =
            dataApiUserStatisticsService.getDataApiTopUserReqDomainList(projectId);

        List<DataApiTopUserReqSummaryDomain> domains = Lists.newArrayList();

        for (int i = 0; i < getDataApiTopUserReqDomainList.size(); i++) {
            domains.add(
                DataApiTopUserReqSummaryDomain.builder()
                    .rank(i + 1)
                    .username(getDataApiTopUserReqDomainList.get(i).getUsername())
                    .totalCount(getDataApiTopUserReqDomainList.get(i).getTotal())
                    .build());
        }
        return domains;
    }

    @Override
    public List<DataApiTopApiReqSummaryDomain> getTopApiReqSummary(
        Integer type, Long projectId, Integer isAuth, String id) {

        List<DataApiTopApiReqSummaryDomain> res1 = Lists.newArrayList();
        // 全局
        List<DataApiDomain> apiUsedTop = Lists.newArrayList();
        if (type == 0) {
            apiUsedTop = dataApiService.getApiUsedTop(projectId, 0, null);
        } else {
            apiUsedTop = dataApiService.getApiUsedTop(projectId, 0, id);
        }
        for (int i = 0; i < apiUsedTop.size(); i++) {
            DataApiDomain dataApiEntity = apiUsedTop.get(i);
            DataApiTopApiReqSummaryDomain domain =
                DataApiTopApiReqSummaryDomain.builder()
                    .rank(i + 1)
                    .apiName(dataApiEntity.getApiName())
                    .totalCount(dataApiEntity.getTotalCount())
                    .build();
            res1.add(domain);
        }

        return res1;
    }

    @Override
    public List<DataApiTopApiReqSummaryDomain> getTopApiErrReqSummary(
        Integer type, Long projectId, Integer isAuth, String id) {

        List<DataApiTopApiReqSummaryDomain> res1 = Lists.newArrayList();
        // 全局
        List<DataApiDomain> apiUsedTop = Lists.newArrayList();

        if (type == 0) {
            apiUsedTop = dataApiService.getApiUsedTop(projectId, 1, null);
        } else {
            apiUsedTop = dataApiService.getApiUsedTop(projectId, 1, id);
        }
        for (int i = 0; i < apiUsedTop.size(); i++) {
            DataApiDomain dataApiEntity = apiUsedTop.get(i);
            DataApiTopApiReqSummaryDomain domain =
                DataApiTopApiReqSummaryDomain.builder()
                    .rank(i + 1)
                    .apiName(dataApiEntity.getApiName())
                    .totalCount(dataApiEntity.getFailCount())
                    .build();
            res1.add(domain);
        }

        return res1;
    }

    @Override
    public List<DataApiErrDistributionSummaryDomain> getErrDistributionSummary(
        Integer type, Long projectId, Integer isAuth, String id) {

        List<DataApiErrDistributionSummaryDomain> res = Lists.newArrayList();
        if (type == 0) {
            res = dataApiCallRecordService.getErrDistributionSummary(projectId, null);
        } else {
            res = dataApiCallRecordService.getErrDistributionSummary(projectId, id);
        }
        return res;
    }
}
